
#include "EggNinePCH.h"

#include "gl/glew.h"
#include "technique.h"
#include "glfx/glfx.h"

#include <cassert>
#include <cstdio>
#include <string>
#include <map>

using namespace std;

namespace EggNine {

IProgram::IProgram(const string& name, const string& alias)
    :   m_name(name)
    ,   m_alias(alias)
    ,   m_programId(0)
{
}

IProgram::~IProgram()
{
    for(map<string, TexUnit>::const_iterator it=m_texUnits.begin(); it!=m_texUnits.end(); ++it)
        glDeleteSamplers(1, &it->second.m_sampler);
    glUseProgram(0);
    if(m_programId!=0)
        glDeleteProgram(m_programId);
}

GLint IProgram::GetAttribLocation(const string& attr) const
{
    return m_attribMap.at(attr);
}

void IProgram::SetSourceTextures() const
{
    for(map<string, TexUnit>::const_iterator it=m_texUnits.begin(); it!=m_texUnits.end(); ++it)
        if(it->second.m_location>0)
            glBindSampler(it->second.m_unit, it->second.m_sampler);
}

void IProgram::SetTargetTexture(GLuint texId, GLenum target) const
{
    assert(target==GL_TEXTURE_2D || target==GL_TEXTURE_RECTANGLE);

    m_targetTex=texId;
    m_targetType=target;
}

void IProgram::AttachGlobalUniforms(const UniformMap& uBlocks)
{
    m_uBlocks.clear();

    GetActiveUniforms(uBlocks);

    for(unsigned i=0; i<m_uBlocks.size(); i++)
        m_uBlocks[i]->BindToProgram(m_programId, i);

    MapTextures();
}

void IProgram::MapTextures() const
{
    for(map<string, TexUnit>::const_iterator it=m_texUnits.begin(); it!=m_texUnits.end(); ++it)
        if(it->second.m_location>0)
            glProgramUniform1i(m_programId, it->second.m_location, it->second.m_unit);
}

void IProgram::ResetToProgram() const
{
    ResetStateToProgram();
    SetSourceTextures();

    for(unsigned i=0;i<m_uBlocks.size();i++)
        m_uBlocks[i]->BindToState(i);
}

void IProgram::SetTexture(const string& texName, GLuint texId) const
{
    map<string, TexUnit>::const_iterator it=m_texUnits.find(texName);
    assert(it!=m_texUnits.end());

    glActiveTexture(GL_TEXTURE0+it->second.m_unit);
    glBindTexture(it->second.m_target, texId);
}

} // EggNine